package com.tencent.tsf.demo.zuul.filter;

import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.tencent.tsf.gateway.core.annotation.TsfGatewayFilter;
import com.tencent.tsf.gateway.zuul1.filter.TsfGatewayZuulFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * @author liweic
 * @title: TestTsfFilter
 * @description: TestTsfFilter
 * @date 2020/12/16 11:13
 */
@TsfGatewayFilter
public class TestTsfFilter extends TsfGatewayZuulFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(TestTsfFilter.class);

    @Value("${msgw.zuul.enable:true}")
    private boolean enable;

    @Value("${msgw.zuul.header:X-TerminalNo}")
    private String header;

    @Value("${msgw.zuul.province.unit1}")
    private String prov_unit1;

    @Value("${msgw.zuul.province.unit2}")
    private String prov_unit2;

    private List<String> unit1;

    private List<String> unit2;

    private List<String> unit;

    {
        unit1 = new ArrayList<>();
        unit1.add("az4-unit1");
        unit1.add("az5-unit1");

        unit2 = new ArrayList<>();
        unit2.add("az4-unit2");
        unit2.add("az5-unit2");

        unit = new ArrayList<>();
        unit.addAll(unit1);
        unit.addAll(unit2);
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        // 这里一定要设置成MIN_VALUE，否者会被其它过滤器优先处理，可能造成该过滤器介入时机太晚造成处理失败
        return Integer.MIN_VALUE;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();
        String headerStr = context.getRequest().getHeader(header);
        if (headerStr == null || (headerStr.equals(""))) {
            return false;
        }
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        if (unit == null || unit.size() == 0) {
            throw new ZuulRuntimeException(new ZuulException("unit", HttpStatus.INTERNAL_SERVER_ERROR.value(), "unit is null"));
        }

        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest servletRequest = context.getRequest();
        String path = servletRequest.getRequestURI();

        String headerStr = context.getRequest().getHeader(header);
        if (path != null) {
            String[] pathSegments = path.split("/");
            // 例如请求地址为：/msgw/unit2/provider-demo/echo/123
            // 对应的真实地址为：/msgw/az4-unit2/provider-demo/echo/123
            // 其中az4表示实际要访问的可用区，这就是通过header设置的
            if (pathSegments != null && pathSegments.length > 2) {
                int no;
                String prov = null;
                try {
                    int length = headerStr.length();
                    String noStr = headerStr.substring(length - 1, length);
                    no = Integer.parseInt(noStr);
                    if (length >= 2) {
                        prov = headerStr.substring(0, 2);
                    }
                } catch (Exception e) {
                    throw new ZuulRuntimeException(new ZuulException("headerStr", HttpStatus.INTERNAL_SERVER_ERROR.value(), "headerStr parseLong error"));
                }

                if (prov == null) {
                    pathSegments[2] = unit.get(no % (unit.size()));
                } else {
                    if(prov_unit1.contains(prov)){
                        pathSegments[2] = unit1.get(no % (unit1.size()));
                    }else if(prov_unit2.contains(prov)){
                        pathSegments[2] = unit2.get(no % (unit2.size()));
                    }
                }

                String newPath = String.join("/", pathSegments);
                context.set("requestURI", newPath);
            }
        }

        return null;
    }
}
